package com.easylinkin.sm.service.impl;

import com.easylinkin.sm.constant.DictConstant;
import com.easylinkin.sm.constant.LogConstant.Module;
import com.easylinkin.sm.entity.Dict;
import com.easylinkin.sm.mapper.DictMapper;
import com.easylinkin.sm.repository.DictItemRepository;
import com.easylinkin.sm.repository.DictRepository;
import com.easylinkin.sm.service.DictService;
import com.easylinkin.sm.service.I18nService;

import java.util.List;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.morn.boot.data.CrudServiceSupport;
import site.morn.exception.ApplicationMessages;
import site.morn.log.OperateArguments;
import site.morn.rest.RestModel;

/**
 * 数据字典服务
 *
 * @author wujie
 * @since 0.1.1,  2019/08/19
 */
@Slf4j
@Service
@Transactional
public class DictServiceImpl extends
    CrudServiceSupport<Dict, Long, DictRepository> implements
    DictService {

  @Autowired
  private I18nService i18nService;

  @Autowired
  private DictItemRepository dictItemRepository;

  @Resource
  private DictMapper dictMapper;

  @Override
  public List<Dict> getTreeData(Long parentId) {
    String language = LocaleContextHolder.getLocale().toString().toUpperCase();
    return dictMapper.getTreeData(parentId, language, Module.DICT);
  }

  @Override
  public <S extends Dict> S add(RestModel<S> restModel) {
    S model = restModel.getModel();
    this.codeValidate(model.getCode());
    this.nameValidate(model.getParentId(), model.getName());

    S one = super.add(restModel);
    OperateArguments.add(restModel.getModel().getName());
    i18nService.saveI18n(restModel.getAttach(), one.getId(), Module.DICT);
    return one;
  }

  @Override
  public <S extends Dict> S update(RestModel<S> restModel) {
    S model = restModel.getModel();
    this.codeValidate(model.getId(), model.getCode());
    this.nameValidate(model.getParentId(), model.getName(), model.getId());
    //修改时先删除关联国际化
    OperateArguments.add(restModel.getModel().getName());
    this.deleteDictI18n(restModel.getModel().getId());
    i18nService.saveI18n(restModel.getAttach(), null, Module.DICT);
    return super.update(restModel);
  }

  @Override
  public void delete(Long id) {
    //子节点校验
    this.childNodeValidate(id);
    //数据字典校验
    this.dictItemValidate(id);
    //删除国际化
    this.deleteDictI18n(id);
    super.delete(id);
  }

  /**
   * 删除数据字典关联的国际化
   *
   * * @param attach 国际化key
   */
  private void deleteDictI18n(Long key) {
    i18nService.deleteByKeyAndModule(key, Module.DICT);
  }

  /**
   * 子节点校验
   */
  private void childNodeValidate(Long id) {
    List<Dict> list = this.repository().findByParentId(id);
    if (!list.isEmpty()) {
      throw ApplicationMessages.translateException(DictConstant.Error.DELETE_FAIL_HASCHILD)
          .exception();
    }
  }

  /**
   * 子数据字典校验
   */
  private void dictItemValidate(Long dictId) {
    Long count = dictItemRepository.countByDictId(dictId);
    if (count > 0) {
      throw ApplicationMessages.translateException(DictConstant.Error.DELETE_FAIL_HASDICTITEM)
          .exception();
    }
  }

  /**
   * 新增：名称同级校验
   */
  private void nameValidate(Long parentId, String name) {
    List<Dict> list = this.repository().findByNameAndParentId(name, parentId);
    if (!list.isEmpty()) {
      throw ApplicationMessages.translateException(DictConstant.Error.DICT_NAME_REPEAT).exception();
    }
  }

  /**
   * 修改：名称同级校验
   */
  private void nameValidate(Long parentId, String name, Long id) {
    List<Dict> list = this.repository().findByNameAndParentIdAndIdNot(name, parentId, id);
    if (!list.isEmpty()) {
      throw ApplicationMessages.translateException(DictConstant.Error.DICT_NAME_REPEAT).exception();
    }
  }

  /**
   * 新增：字典编码唯一校验
   */
  private void codeValidate(String code) {
    List<Dict> list = this.repository().findByCode(code);
    if (!list.isEmpty()) {
      throw ApplicationMessages.translateException(DictConstant.Error.DICT_CODE_REPEAT).exception();
    }
  }

  /**
   * 修改：字典编码唯一校验
   */
  private void codeValidate(Long id, String code) {
    List<Dict> list = this.repository().findByCodeAndIdNot(code, id);
    if (!list.isEmpty()) {
      throw ApplicationMessages.translateException(DictConstant.Error.DICT_CODE_REPEAT).exception();
    }
  }

}
